package com.jmxcfc.blfsc.langyu.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jmxcfc.blfsc.common.exception.NotifyException;
import com.jmxcfc.blfsc.common.sms.enums.MsgTypeEnum;
import com.jmxcfc.blfsc.common.sms.enums.SendStatusEnum;
import com.jmxcfc.blfsc.common.sms.notify.NotifyDataItem;
import com.jmxcfc.blfsc.common.sms.notify.ResultNotifyRequest;
import com.jmxcfc.blfsc.langyu.entity.SendDetailSub;
import com.jmxcfc.blfsc.langyu.enums.CallBackStatusEnum;
import com.jmxcfc.blfsc.langyu.common.Constants;
import com.jmxcfc.blfsc.langyu.entity.SmsNotifyRecord;
import com.jmxcfc.blfsc.langyu.feign.ISmsClientService;
import com.jmxcfc.blfsc.langyu.service.ISendDetailSubService;
import com.jmxcfc.blfsc.langyu.service.ISmsNotifyRecordService;
import com.jmxcfc.blfsc.langyu.service.ISmsNotifyRequestService;
import com.jmxcfc.fs.common.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 功能描述
 *
 * @author: pay
 * @date: 2024年06月23日 23:25
 */
@Service
@Slf4j
@Transactional(rollbackFor = RuntimeException.class)
public class SmsNotifyRequestServiceImpl implements ISmsNotifyRequestService {

    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    private ISmsClientService smsClientService;
    private ISmsNotifyRecordService smsNotifyRecordService;
    private ISendDetailSubService sendDetailSubService;


    @Autowired
    public void setSmsNotifyRecordService(ISmsNotifyRecordService smsNotifyRecordService) {
        this.smsNotifyRecordService = smsNotifyRecordService;
    }

    @Autowired
    public void setThreadPoolTaskExecutor(ThreadPoolTaskExecutor threadPoolTaskExecutor) {
        this.threadPoolTaskExecutor = threadPoolTaskExecutor;
    }

    @Autowired
    public void setSmsClientService(ISmsClientService smsClientService) {
        this.smsClientService = smsClientService;
    }

    @Autowired
    public void setSendDetailSubService(ISendDetailSubService sendDetailSubService) {
        this.sendDetailSubService = sendDetailSubService;
    }

    /**
     * 处理异步通知数据,处理成功则 返回 ok(若返回其他值任意值，则为接收推送的状态报告失败。我方对于接收失败的会进行三次的重新推送)
     * 处理过程:
     * 1、遍历每条数据:
     * (1)数据落库
     * (2)短信状态判断:errorCode:0表示成功、其他错误码均表示下发失败
     * 2、发送通知的消息队列,到时候blfs-sms消费者进行消费处理
     * @param notifyData
     * @return
     */
    @Override
    public String notifyHandler(Map<String, Objects> notifyData) {

        String handlerResult = "OK";
        try{
            ResultNotifyRequest<JSONObject> notifyRequest = ResultNotifyRequest.of(MsgTypeEnum.SMS);
            String msgId = Optional.ofNullable(String.valueOf(notifyData.get(Constants.CALLBACK_MSG_ID))).orElse("");
            if (smsNotifyRecordService.isNotExist(msgId)) {
                //发送记录明细
                SendDetailSub sendDetailSub = sendDetailSubService.findDetailByMsgId(msgId);
                //通知表留痕
                SmsNotifyRecord smsNotifyRecord = new SmsNotifyRecord();
                //通知blfs-sms请求参数
                List<NotifyDataItem> notifyDataItemList = new ArrayList<>();

                smsNotifyRecord.setReceiver(Optional.ofNullable(String.valueOf(notifyData.get(Constants.CALLBACK_RECEIVER))).orElse(""));
                smsNotifyRecord.setMsgId(Optional.ofNullable(String.valueOf(notifyData.get(Constants.CALLBACK_MSG_ID))).orElse(""));
                smsNotifyRecord.setReportTime(Optional.ofNullable(String.valueOf(notifyData.get(Constants.CALLBACK_REPORT_TIME))).orElse(""));
                smsNotifyRecord.setMobile(Optional.ofNullable(String.valueOf(notifyData.get(Constants.CALLBACK_MOBILE))).orElse(""));
                smsNotifyRecord.setStatus(Optional.ofNullable(String.valueOf(notifyData.get(Constants.CALLBACK_STATUS))).orElse(""));
                smsNotifyRecord.setUuid(Optional.ofNullable(sendDetailSub.getUuid()).orElse(""));
                smsNotifyRecord.setErrorDesc(CallBackStatusEnum.getEnumByValue(Optional.ofNullable(String.valueOf(notifyData.get(Constants.CALLBACK_STATUS))).orElse("")).desc());
                smsNotifyRecordService.save(smsNotifyRecord);

                //通知blfs-sms数据赋值
                NotifyDataItem notifyDataItem = new NotifyDataItem();
                notifyDataItem.setUuid(smsNotifyRecord.getUuid());
                notifyDataItem.setMobile(smsNotifyRecord.getMobile());
                // //判断发送状态是否成功还是失败:errorCode:0表示成功、其他错误码均表示下发失败
                notifyDataItem.setSmsSendStatus(StringUtils.equals(CallBackStatusEnum.DELIVRD.status(), smsNotifyRecord.getStatus()) ? SendStatusEnum.SUCCESS : SendStatusEnum.FAILURE);
                notifyDataItem.setSmsSendStatusDesc(notifyDataItem.getSmsSendStatus().desc());
                notifyDataItem.setErrorCode(smsNotifyRecord.getStatus());
                notifyDataItem.setErrorDesc(smsNotifyRecord.getErrorDesc());
                notifyDataItemList.add(notifyDataItem);

                log.info("朗宇短信状态推送,msgId(短信下发时的唯一值):{},保存通知数据到数据库LANGYU_SMS_NOTIFY_RECORD(朗宇通知表)", smsNotifyRecord.getUuid());
                log.info("朗宇短信状态推送,msgId(短信下发时的唯一值):{},通知数据:{}", smsNotifyRecord.getMsgId(), JSON.toJSONString(notifyDataItem));

                notifyRequest.setNotifyDataList(notifyDataItemList);
                notifyRequest.setEndTime(LocalDateTime.now());
                //异步调用blfs-sms
                threadPoolTaskExecutor.execute(() -> sendNotifyResult(smsNotifyRecord.getUuid(),notifyRequest));

            }else {
                log.error("朗宇短信状态推送,数据库已经存在msgId:{},重复推送数据", msgId);
                handlerResult =  "ERROR";
            }

        }catch (Exception e){
            log.error("朗宇短信状态异步通知处理异常:{}",e.getMessage(),e);
            throw new NotifyException(e);
        }
        return handlerResult;
    }


    /**
     * 发送异步通知,调用blfs-sms
     * @param uuid
     * @param smsNotifyRequest
     * @return
     */
    private void sendNotifyResult(String uuid, ResultNotifyRequest<JSONObject> smsNotifyRequest) {
        try {
            log.info("uuid(短信下发时的唯一值):{},短信状态异步通知调用blfs-sms,调用参数:{}",uuid,JSON.toJSONString(smsNotifyRequest));
            Result<Object> result = smsClientService.receiveNotify(JSON.parseObject(JSON.toJSONString(smsNotifyRequest)));
            log.info("uuid(短信下发时的唯一值):{},短信状态异步通知调用blfs-sms,响应结果:{}",uuid,result);
        } catch (Exception e) {
            log.error("uuid(短信下发时的唯一值):{},朗宇短信状态异步通知处理异常,调用blfs-sms 异常,异常信息:{}", uuid, e.getMessage(), e);
        }
    }
}